﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;

using LowLevelGraphics.Filter;

namespace LowLevelGraphics.Filter
{
    /// <summary>
    /// ExperimentalThinning
    /// </summary>
    public class ExperimentalThinning : ExperimentalMorphology
    {
        protected int m_nIterations = 1;

        public ExperimentalThinning()
            : this(new int[,] {
                {1,1,1},
                {1,1,1},
                {1,1,1}}, 1)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="ExperimentalThinning"/> class.
        /// </summary>
        /// <param name="_aKernel">The _a kernel.</param>
        /// <param name="_nIterations">The _n iterations.</param>
        public ExperimentalThinning(int[,] _aKernel, int _nIterations)
        {
            this.m_aKernel = _aKernel;
            this.m_nIterations = _nIterations;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="ExperimentalThinning"/> class.
        /// </summary>
        /// <param name="_experimentalThinning">The _experimental thinning.</param>
        internal ExperimentalThinning(ExperimentalThinning _experimentalThinning)
        {
            this.m_aKernel = _experimentalThinning.m_aKernel;
            this.m_nIterations = _experimentalThinning.m_nIterations;
        }

        /// <summary>
        /// Gets or sets the iterations.
        /// </summary>
        /// <value>The iterations.</value>
        public int Iterations
        {
            get { return m_nIterations; }
            set { m_nIterations = value; }
        }

        //TODO: check if this can be deleted (inheritance)
        /// <summary>
        /// Gets or sets the kernel.
        /// </summary>
        /// <value>The kernel.</value>
        public int[,] Kernel
        {
            get { return m_aKernel; }
            set { m_aKernel = value; }
        }

        /// <summary>
        /// Executes the specified _bitmap.
        /// </summary>
        /// <param name="_bitmap">The _bitmap.</param>
        public override UnsafeBitmap Execute(UnsafeBitmap _bitmap)
        {
            UnsafeBitmap bitmapCloned = (UnsafeBitmap)_bitmap.Clone();
            UnsafeBitmap bitmap = _bitmap;

            List<int> aKernel = new List<int>();
            foreach (int nValue in this.m_aKernel)
            {
                aKernel.Add(nValue);
            }

            Color colorCloned = Color.Transparent;
            Color color = Color.Transparent;

            int nWidth = bitmap.Width;
            int nHeight = bitmap.Height;

            for (int y = 0; y < nHeight; y++)
            {
                for (int x = 0; x < nWidth; x++)
                {
                    colorCloned = bitmapCloned.GetPixel(x, y);
                    if (colorCloned == Definitions.Black)
                    {
                        int nX = x;
                        int nY = y;
                        foreach (Point pt in Definitions.EnvironmentPointListClockwise)
                        {
                            nX = x + pt.X;
                            nY = y + pt.Y;
                            int nIndex = 0;
                            if (nX > -1 && nX < nWidth - 1 && nY > -1 && nY < nHeight - 1)
                            {
                                if (aKernel[nIndex] == 1)
                                {
                                    bitmap.SetPixel(nX, nY, m_ColorBackground);
                                }
                                nIndex++;
                            }
                        }
                    }
                }
            }
            return _bitmap;
        }

        /// <summary>
        /// This is used to clone a filter, each filter must implement it's own clone functionality
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new ExperimentalThinning(this);
        }
    }
}
